#include "LecteurPhraseSimple.h"

#include <stdlib.h>
#include <iostream>
using namespace std;

////////////////////////////////////////////////////////////////////////////////

LecteurPhraseSimple::LecteurPhraseSimple(string nomFich) :
ls(nomFich) {
}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::analyse() {
    programme();
    cout << "Syntaxe correcte." << endl;
}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::programme() {
    // <programme> ::= debut <seqInst> fin <EOF>

    sauterSymCour("debut");
    seqInst();
    sauterSymCour("fin");
    testerSymCour("<FINDEFICHIER>");
}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::seqInst() {
    // <seqInst> ::= <inst> ; { <inst> ; }

    do {
	inst();
	sauterSymCour(";");
    } while (ls.getSymCour() == "<VARIABLE>" || ls.getSymCour() == "si" || ls.getSymCour() == "tantque" || ls.getSymCour() == "repeter" || ls.getSymCour() == "pour");
    // tant que le symbole courant est un debut possible d'instruction...
}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::inst() {
    // <inst> ::=  <affectation> | <instSi> | <instTq> | <instRepeter>
    if (ls.getSymCour() == "si" || ls.getSymCour() == "tantque" || ls.getSymCour() == "repeter" || ls.getSymCour() == "pour") {
	instSi();
	instTq();
	instRepeter();
	instPour();
    } else if (ls.getSymCour() == "lire" || ls.getSymCour() == "ecrire") {
	instLire();
	instEcrire();
    } else {
	affectation();
    }

}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::instSi() {
    //  <instSi>  ::= si ( <expBool> ) <seqInst> { sinonsi ( <expBool> ) <seqInst> [ sinon <seqInst> ] finsi 
    if (ls.getSymCour() == "si") {
	sauterSymCour("si");
	sauterSymCour("(");
	expBool();
	sauterSymCour(")");
	sauterSymCour("alors");
	seqInst();
	while (ls.getSymCour() == "sinonsi") {
	    sauterSymCour("sinonsi");
	    sauterSymCour("(");
	    expBool();
	    sauterSymCour(")");
	    sauterSymCour("alors");
	    seqInst();
	}
	if (ls.getSymCour() == "sinon") {
	    ls.suivant();
	    seqInst();
	}
	sauterSymCour("finsi");


    }
}


void LecteurPhraseSimple::instPour() {
    if (ls.getSymCour() == "pour") {
	sauterSymCour("pour");
	sauterSymCour("(");
	affectation();
	sauterSymCour(";");
	expBool();
	sauterSymCour(";");
	affectation();
	sauterSymCour(")");
	seqInst();
	sauterSymCour("finpour");

    }
}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::instTq() {
    // <instTq>  ::= tantque ( <expBool> ) <seqInst> fintantque
    if (ls.getSymCour() == "tantque") {
	sauterSymCour("tantque");
	sauterSymCour("(");
	expBool();
	sauterSymCour(")");
	seqInst();
	sauterSymCour("fintantque");

    }
}

void LecteurPhraseSimple::instRepeter(){
    // <instRepeter> ::= repeter <seqInst> jusqua ( <expBool> ) 
    if (ls.getSymCour() == "repeter") {
	sauterSymCour("repeter");
	seqInst();
	sauterSymCour("jusqua");
	sauterSymCour("(");
	expBool();
	sauterSymCour(")");

    }
}

void LecteurPhraseSimple::instLire() {
    if (ls.getSymCour() == "lire") {
	sauterSymCour("lire");
	sauterSymCour("(");
	sauterSymCour("<VARIABLE>");
	sauterSymCour(")");
    }
}

void LecteurPhraseSimple::instEcrire() {
    if (ls.getSymCour() == "ecrire") {
	sauterSymCour("ecrire");
	sauterSymCour("(");
	if (ls.getSymCour() == "<CHAINE>") {
	    sauterSymCour("<CHAINE>");
	} else {
	    expression();
	}
	sauterSymCour(")");
    }

}

void LecteurPhraseSimple::affectation() {
    // <affectation> ::= <variable> = <expression>

    sauterSymCour("<VARIABLE>");
    sauterSymCour("=");
    expression();
}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::terme() {
    // <facteur> ::= { <opMult> <facteur> }
    facteur();
    while (ls.getSymCour() == "*" || ls.getSymCour() == "/") {
	opMult();
	facteur();
    }
}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::opAdd() {
    //<opAdd> ::= + | -
    if (ls.getSymCour() == "+" || ls.getSymCour() == "-")
	ls.suivant();
    else
	erreur("<opAdd>");
}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::opMult() {
    //<opMult> ::= * | /
    if (ls.getSymCour() == "*" || ls.getSymCour() == "/")
	ls.suivant();
    else
	erreur("<opMult>");
}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::expBool() {

    //relation();
    //while (ls.getSymCour() == "et" || ls.getSymCour() == "ou") {
    //opBool();
    expBoolEt();
    //relation();
    //}

}

void LecteurPhraseSimple::expBoolEt() {
     //<expBoolEt> ::= <expBoolOu> {et <expBoolOu>}
    expBoolOu();
    while (ls.getSymCour() == "et") {
	sauterSymCour("et");
	expBoolOu();
    }

}

void LecteurPhraseSimple::expBoolOu() {
    //<expBool> ::= <relation> { <opBool> <relation> }
    relation();
    while (ls.getSymCour() == "ou") {
	sauterSymCour("ou");
	relation();
    }
}
/*void LecteurPhraseSimple::opBool() {
=======
////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::opBool() {
>>>>>>> .r16
    // <opBool> ::= et | ou
    if (ls.getSymCour() == "et" || ls.getSymCour() == "ou")
	ls.suivant();
    else
	erreur("<opBool>");
}*/
void LecteurPhraseSimple::opBoolEt() {
    if (ls.getSymCour() == "et")
	ls.suivant();
    else
	erreur("<opBoolEt>");
}

void LecteurPhraseSimple::opBoolOu() {
    if (ls.getSymCour() == "ou")
	ls.suivant();
    else
	erreur("<opBoolOu>");
}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::relation() {
    // <expression>::= { <opRel> <expression> }
    expression();
    while (ls.getSymCour() == "==" || ls.getSymCour() == "!=" || ls.getSymCour() == "<=" || ls.getSymCour() == ">=" || ls.getSymCour() == "<" || ls.getSymCour() == ">") {
	opRel();
	expression();
    }
}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::opRel() {
    // <opRel> ::= == | != | > | >= | < | <=
    if (ls.getSymCour() == "==" || ls.getSymCour() == "!=" || ls.getSymCour() == "<=" || ls.getSymCour() == ">=" || ls.getSymCour() == "<" || ls.getSymCour() == ">")
	ls.suivant();
    else
	erreur("<opRel>");
}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::opUnaire() {
    // <opUnaire> ::= - | non
    if (ls.getSymCour() == "-" || ls.getSymCour() == "non")
	ls.suivant();
    else
	erreur("<opUnaire>");
}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::expression() {
    // <expression> ::= <terme> { <opAdd> <terme> }

    terme();
    while (ls.getSymCour() == "+" || ls.getSymCour() == "-" ||
	    ls.getSymCour() == "*" || ls.getSymCour() == "/") {
	opAdd();
	terme();
    }
}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::facteur() {
    // <facteur> ::= <entier>  |  <variable>  |  - <facteur>  |  ( <expression> )

    if (ls.getSymCour() == "<VARIABLE>" || ls.getSymCour() == "<ENTIER>") {
	ls.suivant();
    } else if (ls.getSymCour() == "-" || ls.getSymCour() == "non") {
	opUnaire();
	expBool();
    } else if (ls.getSymCour() == "(") {
	sauterSymCour("(");
	expBool();
	sauterSymCour(")");
    } else
	erreur("<facteur>");
}

////////////////////////////////////////////////////////////////////////////////
/*void LecteurPhraseSimple::opBinaire()
// <opBinaire> ::= + | - | *  | /
{
	if (ls.getSymCour()=="+" || ls.getSymCour()=="-" || 
		ls.getSymCour()=="*" || ls.getSymCour()=="/")
		ls.suivant();
	else
		erreur("<opBinaire>");
}
 */
////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::testerSymCour(string ch) {
    if (ls.getSymCour() != ch) {
	cout << endl << "-------- Erreur ligne " << ls.getLigne()
		<< " - Colonne " << ls.getColonne() << endl << "   Attendu : "
		<< ch << endl << "   Trouve  : " << ls.getSymCour() << endl
		<< endl;
	exit(0); // plus tard, on levera une exception
    }
}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::sauterSymCour(string ch) {
    testerSymCour(ch);
    ls.suivant();
}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::erreur(string mess) {
    cout << endl << "-------- Erreur ligne " << ls.getLigne() << " - Colonne "
	    << ls.getColonne() << endl << "   Attendu : " << mess << endl
	    << "   Trouve  : " << ls.getSymCour() << endl << endl;
    exit(0); // plus tard, on levera une exception
}

////////////////////////////////////////////////////////////////////////////////
